import os
from datetime import datetime

from flask import g
from sqlalchemy import and_

from app import serializer
from app.models import db
from app.models.car import CarInfo
from werkzeug.utils import secure_filename
from common.utils.image_tools import save_image, get_link

from app.models.collection import (
    DataCollection,
    CollectionImage,
    ParkingCollection,
    ParkingCollectionImage,
)
from marshmallow import (
    fields,
    Schema,
    validates_schema,
    ValidationError,
    post_load,
    pre_load,
    pre_dump,
)

from common.utils.db import TotalNumberSerializer
from common.utils.backends import AliyunOssStorage


ali_oss = AliyunOssStorage()


class ParkingCollectionPutSerizlizer(serializer.SQLAlchemySchema):
    class Meta:
        model = ParkingCollection
        fields = [
            "id",
            "create_time",
            "update_time",
            "collection_type",
            "city",
            "find_park_time",
            "find_park_end_time",
            "stop_time",
            "end_time",
            "parking_type",
            "excavate",
            "place_type",
            "time_type",
            "othen_type",
            "park_user",
            "park_num",
            "upload",
            "collection_place",
            "follow_user",
            "remarks",
            "car",
        ]

    @pre_load
    def befor_create_collection(self, data, many, **kwargs):
        body_dict = {}
        for key, value in data.items():
            if value:
                if key in [
                    "create_time",
                    "update_time",
                    "stop_time",
                    "end_time",
                    "find_park_time",
                    "find_park_end_time",
                ]:
                    value = value.split(".")[0]
                body_dict[key] = value

        return body_dict

    @validates_schema
    def validates_data(self, data, **kwargs):
        pass

    @post_load
    def put_collection_info(self, data, many, **kwargs):
        # 报存数据对象
        pk = data.pop("id")

        if not data:
            return 1
        try:
            collection = ParkingCollection.query.filter(ParkingCollection.id == pk).update(data)
        except Exception as e:
            raise e
        db.session.commit()
        return collection


class parkingCollectionIdSerizlizer(serializer.SQLAlchemySchema):
    class Meta:
        model = ParkingCollection
        fields = ["id"]


class ParyingCollectionPostSerizlizer(serializer.SQLAlchemySchema):
    class Meta:
        model = ParkingCollection
        fields = [
            "create_time",
            "update_time",
            "collection_type",
            "city",
            "find_park_time",
            "find_park_end_time",
            "stop_time",
            "end_time",
            "parking_type",
            "excavate",
            "place_type",
            "time_type",
            "othen_type",
            "park_user",
            "park_num",
            "upload",
            "collection_place",
            "follow_user",
            "remarks",
            "car",
            "user",
        ]

    @pre_load
    def befor_create_collection(self, data, many, **kwargs):

        body_dict = {}
        if g.user_id:
            body_dict["user"] = g.user_id

        for key, value in data.items():
            if value:
                if key in [
                    "create_time",
                    "update_time",
                    "stop_time",
                    "end_time",
                    "find_park_time",
                    "find_park_end_time",
                ]:
                    value = value.split(".")[0]
                body_dict[key] = value

        return body_dict

    @validates_schema
    def validates_data(self, data, **kwargs):
        pass

    @post_load
    def create_collection_info(self, data, many, **kwargs):
        # 报存数据对象

        collection = ParkingCollection(**data)

        db.session.add(collection)
        db.session.commit()

        return collection


class CarInfoSerizlizer(serializer.Schema):
    id = fields.Integer()
    car_num = fields.String()
    asset_code = fields.String()
    vin_num = fields.String()
    deleted = fields.Boolean()
    create_time = fields.DateTime()


class ParkingCollectionImagePostQuerySerizlizer(serializer.Schema):
    files = fields.String()
    parking_collection_id = fields.Integer()

    @post_load
    def save_image(self, data, many, *args, **kwargs):
        try:
            collection = ParkingCollection.query.get(data.get("parking_collection_id"))
        except Exception as e:
            raise ValidationError

        # 保存图片

        file = self.context.get("request").files.get("files")
        file_name = save_image(file)
        image = ParkingCollectionImage(file=file_name, parking_collection=collection.id)

        db.session.add(image)

        db.session.commit()

        return image


class ParkingCollectionImageIdSerizlizer(serializer.SQLAlchemySchema):
    class Meta:
        model = ParkingCollectionImage
        fields = ["id"]


class ParkingCollectionImageSerizlizer(serializer.SQLAlchemySchema):
    class Meta:
        model = ParkingCollectionImage
        fields = ["id", "file", "parking_collection"]

    @pre_dump
    def image_body(self, data, many, *args, **kwargs):

        data.file = get_link(data.file)

        return data


class ParkingCollectionBodySerizlizer(serializer.SQLAlchemySchema):
    cars = fields.Nested(CarInfoSerizlizer())
    images = fields.Nested(ParkingCollectionImageSerizlizer(many=True))

    class Meta:
        model = ParkingCollection
        fields = [
            "id",
            "create_time",
            "update_time",
            "collection_type",
            "city",
            "find_park_time",
            "find_park_end_time",
            "stop_time",
            "end_time",
            "parking_type",
            "place_type",
            "time_type",
            "othen_type",
            "park_user",
            "excavate",
            "park_num",
            "upload",
            "collection_place",
            "follow_user",
            "remarks",
            "cars",
            "images",
        ]


class ParkingCollectionDataSerizlizer(serializer.SQLAlchemySchema, TotalNumberSerializer):
    data = fields.Nested(ParkingCollectionBodySerizlizer(many=True))


class ParkingCollectionQuerySerializer(serializer.SQLAlchemySchema):
    page = fields.Integer()
    per_page = fields.Integer()
    car_num = fields.String()
    start_time = fields.String()
    over_time = fields.String()

    class Meta:
        model = ParkingCollection
        fields = [
            "page",
            "per_page",
            "id",
            "create_time",
            "update_time",
            "collection_type",
            "city",
            "find_park_time",
            "find_park_end_time",
            "stop_time",
            "end_time",
            "parking_type",
            "excavate",
            "place_type",
            "time_type",
            "othen_type",
            "park_user",
            "park_num",
            "upload",
            "collection_place",
            "follow_user",
            "remarks",
            "car",
            "start_time",
            "over_time",
            "car_num",
        ]

    @pre_load
    def befor_data(self, data, many, **kwargs):

        body_dict = {}
        for key, value in data.items():
            if value:
                if key in ["start_time", "over_time"]:
                    value = data[key].split("T")[0].replace('"', "")
                body_dict[key] = value

        return body_dict

    @validates_schema
    def validates_data(self, data, **kwargs):
        pass

    @post_load
    def get_collection_info(self, data, many, **kwargs):
        # 查询数采对象
        page = data.pop("page", 1)
        per_page = data.pop("per_page", 10)
        # data_collections = (
        #     db.session.query(DataCollection).filter_by(**data).paginate(page, per_page)
        # )
        collection_query = []
        if data.get("collection_type"):
            collection_query.append(
                ParkingCollection.collection_type.contains(data.get("collection_type"))
            )
        if data.get("city"):
            collection_query.append(ParkingCollection.city.contains(data.get("city")))

        if data.get("collection_place"):
            collection_query.append(
                DataCollection.collection_place.contains(data.get("collection_place"))
            )
        if data.get("follow_user"):
            collection_query.append(DataCollection.follow_user.contains(data.get("follow_user")))
        if data.get("car_num"):
            collection_query.append(CarInfo.car_num.contains(data.get("car_num")))

        if data.get("start_time") and data.get("over_time"):
            collection_query.append(
                and_(
                    db.cast(DataCollection.create_time, db.DATE)
                    >= db.cast(data.get("start_time"), db.DATE),
                    db.cast(DataCollection.create_time, db.DATE)
                    <= db.cast(data.get("over_time"), db.DATE),
                )
            )
        elif data.get("start_time"):

            collection_query.append(
                db.cast(DataCollection.create_time, db.DATE)
                >= db.cast(data.get("start_time"), db.DATE)
            )

        elif data.get("over_time"):

            collection_query.append(
                db.cast(DataCollection.create_time, db.DATE)
                <= db.cast(data.get("over_time"), db.DATE)
            )

        data_collections = (
            ParkingCollection.query.join(CarInfo, CarInfo.id == ParkingCollection.car)
            .filter(ParkingCollection.deleted == False, *collection_query)
            .order_by(ParkingCollection.id.desc())
            .paginate(per_page=per_page, page=page)
        )

        return data_collections.items, data_collections.total
